package com.redepronik.negosys.utils.service;

import static com.redepronik.negosys.utils.Utils.parametro;
import static com.redepronik.negosys.utils.Utils.presentaMensaje;

import java.awt.Image;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;

import org.springframework.stereotype.Service;

@Service
public class ReporteServiceImpl implements ReporteService {

	private FacesContext facesContext;

	private <T> JasperPrint generadorReporte(String nombreReporte,
			Map<String, Object> parametros, List<T> listaReporte) {
		try {
			String reportPath = facesContext.getExternalContext().getRealPath(
					"/reportes/" + nombreReporte + ".jasper");

			return JasperFillManager.fillReport(reportPath, parametros,
					new JRBeanCollectionDataSource(listaReporte));
		} catch (JRException e) {
			e.printStackTrace();
		}
		return new JasperPrint();
	}

	public <T> void generarReportePDF(List<T> listaReporte,
			Map<String, Object> parametros, String nombreReporte) {
		facesContext = FacesContext.getCurrentInstance();
		if (listaReporte.isEmpty())
			presentaMensaje(FacesMessage.SEVERITY_ERROR,
					"NO HAY DATOS PARA IMPRIMIR");
		else {
			parametros.put("logo", readImage(parametro.getLogo()));
			parametros.put("razonSocial", parametro.getNombrecomercial());
			parametros.put("paginaWeb", parametro.getPaginaweb());
			parametros.put("SUBREPORT_DIR", facesContext.getExternalContext()
					.getRealPath("/reportes") + "/");
			respondeServidor(
					generadorReporte(nombreReporte, parametros, listaReporte),
					nombreReporte);
		}
	}

	public <T> void generarReportePDFSencillo(List<T> listaReporte,
			Map<String, Object> parametros, String nombreReporte) {
		facesContext = FacesContext.getCurrentInstance();
		respondeServidor(
				generadorReporte(nombreReporte, parametros, listaReporte),
				nombreReporte);
	}

	public <T> void generarReporteXLS(List<T> listaReporte,
			Map<String, Object> parametros, String nombreReporte) {
		facesContext = FacesContext.getCurrentInstance();
		try {
			JasperPrint jasperPrint = generadorReporte(nombreReporte,
					parametros, listaReporte);

			JRXlsExporter exporter = new JRXlsExporter();
			exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
			exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME,
					nombreReporte + ".xls");
			exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,
					Boolean.TRUE);
			exporter.exportReport();

			HttpServletResponse httpServletResponse = (HttpServletResponse) facesContext
					.getExternalContext().getResponse();

			httpServletResponse.setContentType("application/vnd.ms-excel");
			httpServletResponse.addHeader("Content-disposition",
					"attachment; filename=" + nombreReporte + ".xls");

			ServletOutputStream servletStream = httpServletResponse
					.getOutputStream();

			File f = new File(nombreReporte + ".xls");
			InputStream in = new FileInputStream(f);
			int bit = 256;
			while (bit >= 0) {
				bit = in.read();
				servletStream.write(bit);
			}

			servletStream.flush();
			servletStream.close();
			in.close();

			facesContext.responseComplete();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public InputStream readImage(byte[] bytes) {
		InputStream bais = new ByteArrayInputStream(bytes);
		Image image = null;
		try {
			image = ImageIO.read(bais);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bais.close();
			} catch (IOException e) {
			}
		}
		if (image == null) {
			return null;
		} else {
			return new ByteArrayInputStream(bytes);
		}
	}

	public void respondeServidor(JasperPrint jasperPrint, String nombreReporte) {
		ExternalContext econtext = facesContext.getExternalContext();
		try {

			HttpServletResponse response = (HttpServletResponse) econtext
					.getResponse();
			response.setContentType("application/pdf");
			response.addHeader("Content-disposition", "inline; filename="
					+ nombreReporte + ".pdf");

			JRExporter exporter = new JRPdfExporter();
			exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
			exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,
					response.getOutputStream());
			exporter.exportReport();
		} catch (Exception e) {
			e.printStackTrace();
		}
		facesContext.responseComplete();
	}
}
